package Control;

import Boundary.Text;
import Entity.DieCup;
import Entity.Player;

public abstract class BaseGame {

	protected final int POINTS_TO_WIN = 40;
	protected Player player1;
	protected Player player2;
	protected Player currentPlayer;
	protected DieCup dieCup;
	protected String shownText = "";
	// Player 1 always starts. However this would work with Player 2, or
	// even random.
	protected int activePlayer = 1;

	/**
	 * Game constructor. Creates new instances of the required classes.
	 */
	public BaseGame() {
		this.player1 = new Player();
		this.player2 = new Player();
		this.dieCup = new DieCup();
	}

	/**
	 * Start the game.
	 */
	public void startGame() {
		// Set the player names and save them in the player objects
		this.player1.setName("Spiller 1");
		this.player2.setName("Spiller 2");

		this.shownText = Text.getRules();
	}

	abstract void writeNextPlayersTurn();

	abstract void statusTasks();

	abstract void winTasks();

	/**
	 * Simple method to get a player object from an integer. Eg. "getPlayer(1)"
	 * will get player1 object.
	 * 
	 * @param playerNo
	 *            The number of the player to get.
	 * @return The player object that corresponds to the number given.
	 */
	protected Player getPlayer(int playerNo) {
		if (playerNo == 1) {
			return this.player1;
		} else if (playerNo == 2) {
			return this.player2;
		}

		return null;
	}

	/**
	 * Simple method to toggle between 1 and 2.
	 * 
	 * @param input
	 *            The number to toggle away from.
	 * @return 1 if 2 is given, 2 if 1 is given.
	 */
	protected int getInactivePlayer(int input) {
		if (input == 1) {
			return 2;
		} else if (input == 2) {
			return 1;
		}

		return 0;
	}

	protected boolean isGameWon() {
		return this.currentPlayer.getAccount() >= this.POINTS_TO_WIN
				&& this.dieCup.getEns();
	}

	protected void takeTurn() {
		// Get data for the active player
		this.currentPlayer = getPlayer(this.activePlayer);

		// Shake, and add the sum of the dice to the current players score
		this.dieCup.shakeDieCup();
		this.currentPlayer.addToAccount(this.dieCup.getSum());

		// Check if player hit double 1's and set score to 0 if he did
		if (this.dieCup.getDoubleOne()) {
			this.currentPlayer.setAccount(0);
		}

		// Check if player hit double 6's and save to player object
		if (this.dieCup.getDoubleSix()) {
			// Check if current player has won by having double 6's two times in
			// a row
			if (this.currentPlayer.getHitSixLast()) {
				statusTasks();
				winTasks();
			}

			// Save double six status AFTER the win-check
			this.currentPlayer.setHitSixLast(true);
		} else {
			this.currentPlayer.setHitSixLast(false);
		}

		// Write status/score to TUI/GUI
		statusTasks();

		// Check if player have won by having enough points and hitting a pair
		if (isGameWon()) {
			winTasks();
		}

		// Switch turn to the other player, unless the current player hit a pair
		if (!this.dieCup.getEns()) {
			this.activePlayer = getInactivePlayer(this.activePlayer);
		}

		if (!isGameWon()) {
			// Write whos turn it is and wait for input
			writeNextPlayersTurn();
		}
	}

}
